/**
 * Created by qiushaohua on 14-3-18.
 */
define(['app',
    'services/HatchStack'
], function (app) {

    var deps = ['$injector', '$rootScope', '$q', '$http', '$templateCache', '$controller', 'HatchStack'];

    function hatchService ($injector, $rootScope, $q, $http, $templateCache, $controller, HatchStack) {

        function getTemplatePromise (options) {
            if (options.template) {
                return $q.when(options.template);
            }
            return $http.get(options.templateUrl, {cache: $templateCache}).then(function (result) {
                return result.data;
            });
        }

        function getResolvePromises (resolves) {
            var promisesArr = [];
            angular.forEach(resolves, function (value, key) {
                if (angular.isFunction(value) || angular.isArray(value)) {
                    promisesArr.push($q.when($injector.invoke(value)));
                }
            });
            return promisesArr;
        }

        var hatch = {};
        hatch.open = function (options) {

            var modalResultDeferred = $q.defer();
            var modalOpenedDeferred = $q.defer();

            // prepare an instance of a modal to be injected into controllers and returned to a caller
            var hatchInstance = {
                result: modalResultDeferred.promise,
                opened: modalOpenedDeferred.promise,
                close: function (result) {
                    HatchStack.close(hatchInstance, result);
                }
            };

            // merge and clean up options
            options = angular.extend({}, options);
            options.resolve = options.resolve || {};

            // verify options
            if (!options.template && !options.templateUrl) {
                throw new Error('One of template or templateUrl options is required.');
            }

            var templateAndResolvePromise =
                $q.all([getTemplatePromise(options)].concat(getResolvePromises(options.resolve)));


            templateAndResolvePromise.then(function resolveSuccess (tplAndVars) {

                var hatchScope = (options.scope || $rootScope).$new();
                hatchScope.$close = hatchInstance.close;

                var ctrlInstance, ctrlLocals = {};
                var resolveIter = 1;

                //controllers
                if (options.controller) {
                    ctrlLocals.$scope = hatchScope;
                    ctrlLocals.hatchInstance = hatchInstance;
                    angular.forEach(options.resolve, function (value, key) {
                        ctrlLocals[key] = tplAndVars[resolveIter++];
                    });

                    ctrlInstance = $controller(options.controller, ctrlLocals);
                }

                HatchStack.open(hatchInstance, {
                    scope: hatchScope,
                    deferred: modalResultDeferred,
                    content: tplAndVars[0],
                    hatchClass: options.hatchClass
                });

            }, function resolveError (reason) {
                modalResultDeferred.reject(reason);
            });

            templateAndResolvePromise.then(function () {
                modalOpenedDeferred.resolve(true);
            }, function () {
                modalOpenedDeferred.reject(false);
            });

            return hatchInstance;
        };

        return hatch;
    }

    hatchService.$inject = deps;
    return app.lazy.service('Hatch', hatchService);
});